﻿#pragma once
#include "../Base/Base.hpp"
#include "../Base/TypeDefine.hpp"
#include "../Base/StringPool.hpp"
#include "../UI/EventArgs.hpp"
#include "../UI/Event.hpp"
#include <set>
namespace NAMESPACENAME
{
	class ContainerControl;
	/// <summary>
	/// 所有控件的基类
	/// </summary>
	class Control
	{
	protected:
		static HMENU GetId(ContainerControl* parent);
		/// <summary>
		/// 父控件
		/// </summary>
		ContainerControl* parent;
		/// <summary>
		/// 仅能由子类调用的构造函数,
		/// 不初始化变量hWnd, 由子控件初始化
		/// </summary>
		/// <param name="parent">父控件</param>
		inline Control(ContainerControl* parent) :
			parent(parent),
			dock(DockStyle::None),
			visibility(Visibility::Hidden)
		{
		}
	public:
		/// <summary>
		/// 获得父控件
		/// </summary>
		/// <returns>父控件</returns>
		inline ContainerControl* Parent()const
		{
			return parent;
		}
	public:
		/// <summary>
		/// 窗口风格
		/// bits使用位域, 可以对指定风格进行设置
		/// groupStyle可以设置一组风格, 若不单独设置风格, 可以直接使用其中的风格
		/// style为风格整体, groupStyle设置风格时应将其或到此变量上
		/// </summary>
		union WindowsStyle
		{
			class
			{
			public:
				unsigned : 16;
				unsigned MaximizeBox : 1;
				unsigned MinimizeBox : 1;
				unsigned ThickFrame : 1;
				unsigned SystemMenu : 1;
				unsigned : 2;
				unsigned DialogFrame : 1;
				unsigned Border : 1;
				unsigned Maximize : 1;
				unsigned ClipChildren : 1;
				unsigned ClipSiblings : 1;
				unsigned Disabled : 1;
				unsigned Visible : 1;
				unsigned Minimize : 1;
				unsigned Child : 1;
				unsigned Popup : 1;
			}bits;
			enum GroupBits : unsigned
			{
				Caption = 0x00C00000U,
				Group = 0x00020000U,
				TabStop = 0x00100000U,
				Iconic = 0x20000000U,
				SizeBox = 0x00040000U,
				OverlappedWindow = 0x00CF0000U,
				PopupWindow = 0x80C80000U,
				ChildWindow = 0x40000000U
			}groupStyle;
			unsigned style;
		};
		/// <summary>
		/// 可见性
		/// </summary>
		enum class Visibility {
			Hidden,
			Visible,
			Maximize,

		};
		/// <summary>
		/// 边框风格
		/// 暂时没有使用
		/// </summary>
		enum class DockStyle
		{
			None,
			Top,
			Bottom,
			Left,
			Right,
			Fill
		};
	protected:
		/// <summary>
		/// 边框
		/// </summary>
		DockStyle dock;
		/// <summary>
		/// 可见性
		/// </summary>
		Visibility visibility;
		/// <summary>
		/// 启用
		/// </summary>
		bool enabled = true;
		/// <summary>
		/// 窗口句柄
		/// </summary>
		HWND hWnd;
	public:
		/// <summary>
		/// 设置窗口的文本
		/// </summary>
		/// <param name="text">文本</param>
		/// <returns>返回this指针使得可以进行Chain式赋值</returns>
		inline Control* Text(String text)
		{
			auto _s(text.UnsafeGetString());
			::SetWindowTextW(hWnd, _s);
			delete[] _s;
			return this;
		}
		/// <summary>
		/// 获得窗口的文本
		/// </summary>
		/// <returns>文本</returns>
		String Text()const;
		/// <summary>
		/// 获得窗口句柄
		/// </summary>
		/// <returns>窗口句柄</returns>
		HWND inline WindowHandle()const
		{
			return hWnd;
		}
		/// <summary>
		/// 获得当前窗口是否启用
		/// </summary>
		/// <returns></returns>
		[[deprecated("该函数以后可能被弃用或更改")]]
		bool inline IsEnabled()const {
			return enabled;
		}
		/// <summary>
		/// 获得当前的可见性
		/// </summary>
		/// <returns>可见性</returns>
		Visibility inline Visibility()const {
			return visibility;
		}
		/// <summary>
		/// 设置当前的可见性
		/// </summary>
		/// <param name="visb">可见性</param>
		virtual void Visibility(enum class Visibility visb);
		/// <summary>
		/// 获得此控件关于父控件的偏移矩形
		/// </summary>
		/// <returns>偏移矩形</returns>
		NAMESPACENAME::Rectangle GetParentOffsetRectangle()const;

		// 没有参数事件的事件句柄
		using EventHandle = Event<void(Control*, EventArgs&)>;
		EventHandle onDestroy, onMouseClick, onClose;
		// 鼠标事件的事件句柄
		using MouseEventHandle = Event<void(Control*, MouseEventArgs&)>;
		MouseEventHandle onLeftButtonUp, onLeftButtonDown, onRightButtonUp, onRightButtonDown, onMouseMove, onMouseHover;
		// 绘图事件的事件句柄
		using PaintEventHandle = Event<void(Control*, PaintEventArgs&)>;
		PaintEventHandle onPaint;
		// 设置窗口大小事件的事件句柄
		using SizeEventHandle = Event<void(Control*, SizeEventArgs&)>;
		SizeEventHandle onSize;
		// 正在设置窗口大小事件的事件句柄
		using SizingEventHandle = Event<void(Control*, SizingEventArgs&)>;
		SizingEventHandle onSizing;
		// 滚动事件的事件句柄
		using ScrollEventHandle = Event<void(Control*, ScrollEventArgs&)>;
		ScrollEventHandle onHorizontalScroll, onVerticalScroll;
#pragma region Events
		virtual void OnCreate();
		virtual void OnDestroy();
		virtual void OnLoad() = 0;
		virtual void OnUnLoad() = 0;
		virtual void OnClose();
		virtual void OnPaint() = 0;
		virtual void OnNcPaint(HRGN hRgn) = 0;
		virtual void OnCommand(UINT message, UINT id, Control* control) = 0;
		virtual void OnLeftButtonUp(MouseEventArgs&);
		virtual void OnLeftButtonDown(MouseEventArgs&);
		virtual void OnRightButtonUp(MouseEventArgs&);
		virtual void OnRightButtonDown(MouseEventArgs&);
		virtual void OnMouseMove(MouseEventArgs&);
		virtual void OnMouseHover(MouseEventArgs&);
		virtual void OnSize(SizeEventArgs&);
		virtual void OnSizing(SizingEventArgs&);
		virtual void OnHorizontalScroll(ScrollEventArgs&);
		virtual void OnVerticalScroll(ScrollEventArgs&);
#pragma endregion
		virtual ~Control() = default;
	public:
		/// <summary>
		/// 弹出消息框
		/// </summary>
		/// <param name="lpszText">wchar_t的字符串, 消息框文本</param>
		/// <param name="lpszCaption">wchar_t的字符串, 消息框标题</param>
		/// <param name="style">消息框风格</param>
		/// <returns>消息框按钮</returns>
		int MessageBox(LPCWSTR lpszText, LPCWSTR lpszCaption = L"Information", UINT style = MB_OK | MB_ICONINFORMATION);
	};
}